package org.paradigmshift.cumulusfracto.filesystem;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.filesys.FileAttribute;
import org.alfresco.jlan.server.filesys.FileInfo;
import org.alfresco.jlan.server.filesys.SearchContext;
import org.alfresco.jlan.server.filesys.TreeConnection;
import org.apache.log4j.Logger;
import com.google.gdata.client.DocumentQuery;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.util.ServiceException;

public class CumulusFractoSearchContext extends SearchContext {
	
	private static final Logger log = Logger.getLogger( CumulusFractoSearchContext.class );
	
	private static final int MAX_RESULTS_PER_PAGE = 100;
	
	private DocumentQuery query;
	private DocumentListFeed searchFeed;
	private List<DocumentListEntry> entries;
	private int index;
	
	public CumulusFractoSearchContext( SrvSession session, TreeConnection tree, String searchString ) throws FileNotFoundException {
		
		if ( session == null ) throw new NullPointerException();
		if ( tree == null ) throw new NullPointerException();
		if ( searchString == null ) throw new NullPointerException();
		
		CumulusFractoClientInfo clientInfo = (CumulusFractoClientInfo) session.getClientInformation();
		
		DocsService docsService = clientInfo.getDocsService();
		
		query = new DocumentQuery( clientInfo.getAllContentsURL() );
		query.setTitleExact( true );
		query.setTitleQuery( searchString );
		query.setMaxResults( MAX_RESULTS_PER_PAGE );
		
		try {
			
			searchFeed = docsService.getFeed( query, DocumentListFeed.class );
		}
		catch ( ServiceException se ) {
			
			throw new FileNotFoundException();
		}
		catch ( IOException ioe ) {
			
			throw new FileNotFoundException();
		}
		
		entries = searchFeed.getEntries();
		this.index = 0;
	}
	
	/**
	 * Return the resume id for the current file/directory. We return the index
	 * of the next file, this is the file/directory that will be returned if the
	 * search is restarted.
	 * 
	 * @return int Resume id.
	 */
	@Override
	public int getResumeId() {
		
		return index;
	}
	
	/**
	 * Determine if there are more files to return for this search
	 * 
	 * @return boolean
	 */
	@Override
	public boolean hasMoreFiles() {
		
		return ( entries.size() > 0 );
	}
	
	/**
	 * Return the next file information for this search
	 * 
	 * @param info FileInfo
	 * @return boolean
	 */
	@Override
	public boolean nextFileInfo( FileInfo fileInfo ) {
		
		if ( entries != null && index < entries.size() ) {
			
			DocumentListEntry entry = searchFeed.getEntries().get( index++ );
				
			int fileAttributes = 0;
			if ( CumulusFractoDiskDrive.isFolder( entry ) ) fileAttributes = FileAttribute.Directory;
			if ( !entry.getCanEdit() ) fileAttributes += FileAttribute.ReadOnly;
			if ( entry.isHidden() ) fileAttributes += FileAttribute.Hidden;
			
			fileInfo.setFileName( entry.getTitle().getPlainText() );
			fileInfo.setFileAttributes( fileAttributes );
			fileInfo.setModifyDateTime( entry.getUpdated().getValue() );
			fileInfo.setCreationDateTime( entry.getPublished().getValue() );
			fileInfo.setFileId( entry.getResourceId().hashCode() );
			
			return true;
		}
		
		return false;
	}
	
	/**
	 * Return the next file name for this search
	 * 
	 * @return String
	 */
	@Override
	public String nextFileName() {
		
		if ( entries != null && index < entries.size() ) {
			
			DocumentListEntry entry = entries.get( index++ );
			return entry.getTitle().getPlainText();
		}
		
		return null;
	}
	
	/**
	 * Restart the search at the specified resume point.
	 * 
	 * @param resumeId Resume point.
	 * @return true if the search can be restarted, else false.
	 */
	@Override
	public boolean restartAt( int resumeId ) {
		
		boolean restartOk = ( entries != null && resumeId >= 0 && resumeId < entries.size());
		if ( restartOk ) index = resumeId;
			
		return restartOk;
	}
	
	/**
	 * Restart the file search at the specified file
	 * 
	 * @param info FileInfo
	 * @return boolean
	 */
	@Override
	public boolean restartAt( FileInfo fileInfo ) {
		
		boolean restartOk = false;
		int tempIndex = 0;
		
		if ( entries != null ) {
			
			while ( tempIndex < entries.size() && !restartOk ) {
				
				DocumentListEntry entry = entries.get( tempIndex );
				if ( entry.getTitle().getPlainText().equals( fileInfo.getFileName() ) ) {
					
					index = tempIndex;
					restartOk = true;
				}
			}
		}
		
		return restartOk;
	}
}
